<?php
// +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
// | NewThink [ Think More,Think Better! ]
// +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
// | Copyright (c) 2016~2018 http://www.newthink.cc All rights reserved.
// +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
// | 版权所有：山西创泰网络科技有限公司
// +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
// | Author: lk Date:2019\3\21 0021 Time:11:19
// +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

namespace app\api\controller;

use app\common\service\CommonService;
use app\common\service\gis\GisStation;
use think\Db;
use think\Request;

header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:POST,GET,OPTIONS');
header('Access-Control-Allow-Headers:Origin,x-requested-with,content-type,Accept');

ini_set('memory_limit', '1024M');

class Gis extends BaseController
{
    static private $companyList = [];
    static private $stationList = [];

    private $json = [];

    private $commonService;

    /**
     * Gis constructor.
     * @param Request $request
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function __construct(Request $request)
    {
        parent::__construct($request);
        //公司列表
        self::$companyList = \db('basic_company')->where('delete_time', 'eq', 0)->field('id,name,short_name')->select();
        self::$companyList = array_column(self::$companyList, null, 'id');

        //站点列表
        self::$stationList = \db('basic_station')->where('station_id', 'neq', 0)->field('id,station_id,name')->select();
        self::$stationList = array_column(self::$stationList, null, 'station_id');

        $this->commonService = new CommonService();
    }

    /**
     * Notes :获取站点实测及预报数据
     * @author lichao   2019/6/12
     */
    public function getStationData()
    {
        $stationData = array();
        try {
            $gisService  = new GisStation();
            $stationData = $gisService->mergeStationData();
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }

        $this->success('获取站点数据成功', $stationData);
    }

    /**
     * Notes :获取5个站点14天数据
     * @author lichao   2019/6/13
     */
    public function getStationDataByName()
    {
        $stationData = array();
        try {
            $param       = $this->request->param('param', 'pm25');
            $gisService  = new GisStation();
            $stationData = $gisService->getStationData($param);
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }

        $this->success('获取站点数据成功', $stationData);
    }

    /**
     * 获取公司坐标信息
     * @author Naomi
     */
    public function getCompanyData(GisStation $gisStation)
    {
        $param = $this->request->param();

        $where = "WHERE delete_time = 0";
        if (!empty($param['industry_id'])) {
            $where .= " AND industry_id = {$param['industry_id']}";
        }

        if (!empty($param['region_id'])) {
            $where .= " AND region_id = {$param['region_id']}";
        }

        $data = $gisStation->getCompanyData($where);
        $this->success("成功", $data);
    }

    /**
     * 获取公司排量
     * @author Naomi
     */
    public function getEmissions()
    {
        $param         = $this->request->param();
        $param['type'] = $param['type'] ?? 0;
        if (!empty($param['company_id'])) {
            $company_id = $param['company_id'];
            $startDate  = date('Y-m-d', strtotime("-7 day"));
            if ($company_id == 1) {
                $endDate = date('Y-m-d', strtotime("-1 day"));
                $db      = ['company_industry_monitor_sulfur_day', 'company_industry_monitor_nitre_day'];

                $sql  = "SELECT publish_time,sum(emissions) as emissions FROM `{$db[$param['type']]}` WHERE (publish_time between '{$startDate}' AND  '{$endDate}') AND company_id = 1 GROUP BY `company_id`,`publish_time`";
                $data = Db::query($sql);
            } else {
                $field     = ['emissions_so2_total', 'emissions_nox_total'];
                $sql       = "SELECT sum({$field[$param['type']]}) as emissions FROM `company_industry_monitor_simulation_day_avg` WHERE company_id = {$company_id} GROUP BY `company_id`";
                $emissions = Db::query($sql);
                $data      = [];
                for ($i = 0; $i < 7; $i++) {
                    $data[] = [
                        "publish_time" => date('Y-m-d', strtotime("$startDate +{$i} day")),
                        "emissions"    => $emissions[0]['emissions']
                    ];
                }
            }

            $emissionsData = ['date' => [], 'data' => []];
            $type          = ["so2", "nox"];
            foreach ($data as $key => $value) {
                $emissionsData['date'][]    = $value['publish_time'];
                $emissionsData['data'][0][] = ["name" => $type[$param['type']], "value" => round($value['emissions'] / pow(10, 9), 2)];
            }
            $this->success("成功", $emissionsData);
        } else {
            $this->error('参数错误');
        }
    }

    /**
     * @throws \MongoDB\Driver\Exception\Exception
     * @author  dutongtong   2019/7/5
     */
    public function getPollutantData()
    {
        $mongo = new \MongoDB\Driver\Manager("mongodb://root:Ws4815115!@dds-bp1babc036f87d64-pub.mongodb.rds.aliyuncs.com:3717");
        //查询数据
        $query  = new \MongoDB\Driver\Query([
            'publish_time' => date("Y-m-d")
        ], [
            'projection' => [
                '_id' => 0
            ],
        ]);
        $cursor = $mongo->executeQuery("huanxin.gis_air_quality_pollutant", $query)->toArray();
        $data   = json_decode(json_encode($cursor), true);
        foreach ($data as $k => $v) {
            $this->json[$v['predict_time']][] = [
                "company_id"         => $v['company_id'],
                "site_id"            => $v['site_id'],
                "company"            => $v['company'],
                "company_short_name" => $v['company_short_name'],
                "site"               => $v['site'],
                "tooltip"            => [
                    "pm25" => $this->commonService->contributionRound($v['pm25']) . '%',
                    "so2"  => $this->commonService->contributionRound($v['so2']) . '%',
                    "nox"  => $this->commonService->contributionRound($v['nox']) . '%'
                ]
            ];
        }

        $startTime = date('Y-m-d');
        $endTime   = date('Y-m-d 23:00:00', strtotime('+6day'));
        $dates     = self::getDateFromRange($startTime, $endTime);
        $startH    = date('H', strtotime($startTime));
        $endH      = date('H', strtotime($endTime));
        foreach ($dates['dates'] as $k => $v) {
            for ($i = 0; $i < 24; $i++) {
                $curTime = date("Y-n-j $i", strtotime($v));
                $curDate = date("Y-n-j", strtotime($v));
                if (($k == 0 && $i < $startH) || ($k == (count($dates['dates']) - 1) && $i > $endH)) {
                    continue;
                }
                !isset($this->json[$curDate]) && $this->json[$curDate] = [];
                !isset($this->json[$curTime]) && $this->json[$curTime] = [];
            }
        }
        $this->success('数据获取成功!', $this->json);
    }

    /**
     * @throws \MongoDB\Driver\Exception\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author  dutongtong   2019/8/15
     */
    public function getPollutantCompanyByDate()
    {
        $date      = $this->request->param('date', date('Y-m-d'));
        $stationId = $this->request->param('station_id', 1);

        $tables = [
            'hour' => 'huanxin.air_quality_pollutant_company_forecast_hour_handle_day',
            'day'  => 'huanxin.air_quality_pollutant_company_forecast_day',
        ];

        $mongo = new \MongoDB\Driver\Manager("mongodb://root:Ws4815115!@dds-bp1babc036f87d64-pub.mongodb.rds.aliyuncs.com:3717");
        //查询数据
        $query  = new \MongoDB\Driver\Query([
            'publish_time'       => strlen($date) <= 10 ? date('Y-m-d 00:00:00') : date('Y-m-d 23:00:00', strtotime('-1day')),
            'predict_time'       => date('Y-m-d 00:00:00', strtotime($date)),
            'station_id'         => (int)$stationId,
            'contribution_value' => ['$ne' => 0]
        ], ['projection' => ['_id' => 0]]);
        $cursor = $mongo->executeQuery(strlen($date) <= 10 ? $tables['day'] : $tables['hour'], $query)->toArray();
        $res    = json_decode(json_encode($cursor), true);

        $polArr = [
            'PM2.5' => 'pm25',
            'SO2'   => 'so2',
            'NO2'   => 'no2',
        ];
        $list   = [];
        foreach ($res as $k => $v) {
            $companyId = $v['company_id'];

            if(!isset($list[$companyId])){
                $list[$companyId]['pm25'] = 0;
                $list[$companyId]['so2'] = 0;
                $list[$companyId]['no2'] = 0;
            }

            $name      = $polArr[$v['contribution_name']];
            //根据污染物分组
            $list[$companyId]['predict_time']       = $date;
            $list[$companyId]['company_id']         = $companyId;
            $list[$companyId]['site_id']            = $stationId;
            $list[$companyId]['company']            = static::$companyList[$companyId]['name'];
            $list[$companyId]['company_short_name'] = static::$companyList[$companyId]['short_name'];
            $list[$companyId]['site']               = self::$stationList[$stationId]['name'];
            $list[$companyId][$name]                = $v['contribution_value'];
        }
        $list          = array_values($list);
        $companyIds    = array_column($list, 'company_id');
        $companyList   = db::name('basic_company')->field('id,name,longitude,latitude')->whereIn('id', $companyIds)->select();
        $stationInfo   = db::name('basic_station')->field('id,name,longitude,latitude')->where(['station_id' => $stationId])->find();
        $companyList[] = $stationInfo;

        $data['line_list']     = $list;
        $data['location_info'] = $companyList;

        $this->success('获取溯源连线数据成功!', $data);
    }

    /**
     * 获取月平均贡献度
     * @throws \MongoDB\Driver\Exception\Exception
     * @author  dutongtong   2019/6/20
     */
    public function getMonthPollutant()
    {
        $pollutantName = $this->request->param('name');
        $companyId     = $this->request->param('company_id');
        $stationId     = $this->request->param('station_id');

        $validate = V([
            'name'       => 'require',
            'company_id' => 'require',
            'station_id' => 'require'
        ]);
        if (isset($validate['msg'])) $this->error($validate['msg']);
        $mongo = new \MongoDB\Driver\Manager("mongodb://root:Ws4815115!@dds-bp1babc036f87d64-pub.mongodb.rds.aliyuncs.com:3717");

        $document = [
            'aggregate'    => 'air_quality_pollutant_company_forecast_day',
            'pipeline'     => [
                [
                    '$project' => [
                        '_id'                 => 0,
                        'predict_time'        => 1,
                        'publish_time'        => 1,
                        'company_id'          => 1,
                        'industry_id'         => 1,
                        'station_id'          => 1,
                        'contribution_name'   => 1,
                        'contribution_value'  => 1,
                        'contribution_degree' => 1,
                        'concentration'       => 1,
                        'difference'          => ['$eq' => ['$publish_time', '$predict_time']]
                    ]
                ],
                [
                    '$match' => [
                        'difference'        => true,
                        // 'industry_id'       => ['$in' => [1, 2, 3, 4]],
                        'station_id'        => (int)$stationId,
                        'company_id'        => (int)$companyId,
                        'contribution_name' => $pollutantName,
                        'predict_time'      => [
                            '$gte' => date("Y-m-d 00:00:00", strtotime("last month -1day")),
                            '$lte' => date("Y-m-d 00:00:00", strtotime("-1day")),
                        ]
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];
        $command  = new \MongoDB\Driver\Command($document);
        $rows     = $mongo->executeCommand('huanxin', $command)->toArray();
        $data     = json_decode(json_encode($rows[0], 320), true)['result'];

        $new['already'] = [];
        $new['not']     = [];
        foreach ($data as $k => $v) {
            $index         = $v['contribution_value'] > 0 ? 'already' : 'not';
            $new[$index][] = $v;
        }

        $contribution  = array_sum(array_column($data, 'contribution_value'));
        $concentration = array_sum(array_column($data, 'concentration'));
        $data          = [
            'contribution'     => [
                [
                    'name'  => '已贡献',
                    'value' => count($new['already']) * 24
                ],
                [
                    'name'  => '未贡献',
                    'value' => round((strtotime("-1day") - strtotime("last month -1day"))/3600/24) * 24 - count($new['already']) * 24
                ]
            ],
            'contribution_avg' => [
                'date' => [
                    date("m/d", strtotime("last month -1day")) . ' - ' . date("m/d", strtotime("-1day"))
                ],
                'data' => [
                    [
                        $concentration == 0 ? 0 : $this->commonService->contributionRound($contribution / $concentration)
                    ]
                ]
            ]
        ];
        $this->success('获取成功', $data);
    }

    /**
     * 获取运行浓度及效率
     */
    public function getOperationData()
    {
        $param = $this->request->param();
        if (empty($param['company_id']) || empty($param['drain_id']) || empty($param['type']) || empty($param['hourage'])) {
            $this->error('参数错误');
        }
        $startTime = date('Y-m-d H:00:00', strtotime("-{$param['hourage']} hour"));
        $endTime   = date('Y-m-d H:00:00', strtotime("-1 hour"));
        if ($param['company_id'] == 1) {
            $where = "";
            if (!empty($param['facility_id'])) {
                $where = " AND facility_id = {$param['facility_id']}";
            }
            $db    = ['company_industry_monitor_nitre_hour', 'company_industry_monitor_sulfur_hour'];
            $field = ["operation_concentration as operation_concentration_nox,operating_efficiency as operating_efficiency_nox", "operation_concentration as operation_concentration_so2,operating_efficiency as operating_efficiency_so2"];

            $sql  = "SELECT publish_time,{$field[$param['type']-1]} FROM `{$db[$param['type']-1]}` WHERE (publish_time between '{$startTime}' AND '{$endTime}') AND company_id = {$param['company_id']} AND drain_id = {$param['drain_id']} {$where}";
            $data = Db::query($sql);
        } else {
            $dates  = self::getDateFromRange($startTime, $endTime);
            $startH = date('H', strtotime($startTime));
            $endH   = date('H', strtotime($endTime));
            $date   = [];
            foreach ($dates['dates'] as $k => $v) {
                for ($i = 0; $i < 24; $i++) {
                    if (($k == 0 && $i < $startH) || ($k == (count($dates['dates']) - 1) && $i > $endH)) {
                        continue;
                    }
                    $date[] = date("Y-m-d $i:00:00", strtotime($v));
                }
            }

            $field          = ["`publish_hour`,`operation_concentration_nox`,`operating_efficiency_nox`", "`publish_hour`,`operation_concentration_so2`,`operating_efficiency_so2`"];
            $sql            = "SELECT {$field[$param['type']-1]} FROM `company_industry_monitor_simulation_hour_avg` WHERE company_id = {$param['company_id']} AND drain_id = {$param['drain_id']}";
            $simulationData = Db::query($sql);
            $data           = [];
            foreach ($date as $key => $value) {
                foreach ($simulationData as $k => $v) {
                    if (date('H:00:00', strtotime($v['publish_hour'])) == date('H:00:00', strtotime($value))) {
                        unset($v['publish_hour']);
                        $v['publish_time'] = $value;
                        $data[]            = $v;
                    }
                }
            }
        }
        $db = ['company_industry_monitor_sulfur_day', 'company_industry_monitor_nitre_day'];

        $eData = [['data' => [], 'date' => []], ['data' => [], 'date' => []]];
        $index = [["operation_concentration_nox", "operating_efficiency_nox"], ["operation_concentration_so2", "operating_efficiency_so2"]];
        foreach ($data as $key => $value) {
            $eData[0]['date'][]    = $value['publish_time'];
            $eData[0]['data'][0][] = round($value[$index[$param['type'] - 1][0]], 1);
            $eData[1]['date'][]    = $value['publish_time'];
            $eData[1]['data'][0][] = round($value[$index[$param['type'] - 1][1]] * 100, 1);
        }
        $this->success("成功", $eData);
    }

    /**
     * 获取指定日期段内每一天的日期和天数
     * @param string $startDate 开始日期 格式化时间 Y-m-d H:i:s
     * @param string $endDate 结束日期 格式化时间 Y-m-d H:i:s
     * @return array
     */
    public static function getDateFromRange($startDate, $endDate)
    {
        $startDate  = date('Y-m-d 00:00:00', strtotime($startDate));
        $endDate    = date('Y-m-d 23:59:59', strtotime($endDate));
        $sTimestamp = strtotime($startDate);
        $eTimestamp = strtotime($endDate);
        if ($eTimestamp < $sTimestamp) return [];
        // 计算日期段内有多少天
        $days = (int)ceil(($eTimestamp - $sTimestamp) / 86400);
        // 保存每天日期
        $date = array();
        for ($i = 0; $i < $days; $i++) {
            $date[] = date('Y-m-d', $sTimestamp + (86400 * $i));
        }
        $data = [
            'dates' => $date,
            'days'  => $days,
        ];
        return $data;
    }

    /**
     * 获取nc数据
     * @throws \Exception
     */
    public function getNcData()
    {
        $param = $this->request->param();
        $type  = $param['type'] ?? 1;
        $date  = $param['date'] ?? date('Y-n-j');
        $type  = (string)$type;
        $date  = (string)$date;

        //服务器配置
        $ssh_user = 'phpython';//登陆linux的ssh2用户名
        $ssh_pwd  = 'G4GUfzZBwe6t';//登陆linux的密码
        $ssh_port = '22';//端口号22
        $ssh_host = '39.97.181.198';//服务器IP地址
        if (!function_exists("ssh2_connect")) {
            throw new \Exception('SSH扩展没有安装或者没有安装成功');
        }

        //建立ssh2连接
        $ssh2 = ssh2_connect($ssh_host, $ssh_port);
        if (!$ssh2) {
            throw new \Exception('连接服务器失败');
        }

        //连接成功后进行密码验证，没验证无法进行其他操作
        if (!ssh2_auth_password($ssh2, $ssh_user, $ssh_pwd)) {
            throw new \Exception('验证失败');
        }

        //执行shell命令获取数据
        $e      = "/phpython/nc_data/nc_data {$type} {$date}";
        $stream = ssh2_exec($ssh2, $e);

        //流处理
        stream_set_blocking($stream, true);
        $data = stream_get_contents($stream);

        //数据处理并返回
        $data = json_decode($data, true);
        if ($data['code'] === 1) {
            unset($data['code']);
            $this->success('成功', $data);
        }
        $this->error('获取数据失败');
    }
}
